package l1j.opqlo.NewSystem;

import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.opqlo.Server.L1World.L1World;
import l1j.opqlo.Server.L1World.WorldClan;
import l1j.opqlo.Server.L1World.WorldWar;
import l1j.opqlo.假人系統.RobotTable;
import l1j.server.Config;
import l1j.server.DatabaseFactory;
import l1j.server.echo.ClientThread;
import l1j.server.server.BadNamesList;
import l1j.server.server.clientpackets.C_CreateChar;
import l1j.server.server.datatables.BuddyTable;
import l1j.server.server.datatables.CharObjidTable;
import l1j.server.server.datatables.CharacterTable;
import l1j.server.server.datatables.MailTable;
import l1j.server.server.datatables.lock.ClanEmblemReading;
import l1j.server.server.datatables.lock.ClanReading;
import l1j.server.server.model.L1Clan;
import l1j.server.server.model.L1War;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.serverpackets.S_ServerMessage;
import l1j.server.server.utils.SQLUtil;

public class change_name {// 改名卡
	private static Logger _log = Logger.getLogger(C_CreateChar.class.getName());

	private static change_name _instance;

	public static change_name getInstance() {
		if (_instance == null) {
			_instance = new change_name();
		}
		return _instance;

	}

	public void change(final L1PcInstance pc, final String newName) {

		if (newName != null && pc != null) {
			final String temp = newName;
			final String error1 = " ";
			final String error2 = "　";
			final int temp1 = temp.indexOf(error1);
			final int temp2 = temp.indexOf(error2);
			if (temp1 > 0 && temp2 > 0) {
				pc.sendPackets(new A_ColorMessage(15, "名稱包含違規字元，請重新輸入。"));
				pc.sendPackets(new A_ColorMessage(1,
						"請在對話框輸入:\n在你要的名稱前加上[新名稱]\n例如:新名稱" + pc.getName()
								+ "\n變更後角色名稱為:" + pc.getName()));
				return;
			}
			if (this.isInvalidName(newName)) {
				pc.sendPackets(new A_ColorMessage(15, "名稱字數錯誤，請重新輸入。"));
				pc.sendPackets(new A_ColorMessage(1,
						"請在對話框輸入:\n在你要的名稱前加上[新名稱]\n例如:新名稱" + pc.getName()
								+ "\n變更後角色名稱為:" + pc.getName()));
				return;
			}
			if (this.doesCharNameExist(newName)) {
				pc.sendPackets(new A_ColorMessage(15, "名稱已被使用，請重新輸入。"));
				// pc.sendPackets(new
				// S_SystemMessage("請輸入新的角色名稱，完成後請按「Enter」。"));
				pc.sendPackets(new A_ColorMessage(1,
						"請在對話框輸入:\n在你要的名稱前加上[新名稱]\n例如:新名稱" + pc.getName()
								+ "\n變更後角色名稱為:" + pc.getName()));
				return;
			}
			try {
				L1World.getInstance().removeKillerIdForChangeName(pc.getId());//清除仇殺清單
				pc.saveInventory();
				pc.sendPackets(new A_ColorMessage(1, "角色名稱修改成功!!自動斷線。"));
				final ClientThread ct = pc.getNetConnection();
				Thread.sleep(1000);
				CharObjidTable.get().charRemove(pc.getName());
				this.leaveClan(pc);
				this.removeBuddys(pc);
				// TODO 使用物品記錄by opqlo
				final StringBuilder aa = new StringBuilder(32).append("IP(")
						.append(pc.getNetConnection().getIp().toString()).append(") 帳號: [").append(pc.getAccountName())
						.append(" ]玩家:【").append(pc.getName())
						.append("】更改名稱為:【").append(newName).append("】時間:(")
						.append(new Timestamp(System.currentTimeMillis()))
						.append(")。");

				各項記錄輸出.LogSave(14, aa.toString());
				aa.delete(0, aa.length());
				_log.info("玩家[ " + pc.getName() + " ]更改名稱後中斷連線。");

				// TODO 使用物品記錄by opqlo
				pc.setChangeName(0);
				MailTable.getInstance().setMailByChangeName(pc.getName() , newName);
				CharacterTable.getInstance().UpdateCharName(pc, newName);
				this.ChangeName(pc, newName);
				ct.setActiveChar(pc);
				CharObjidTable.get().addChar(pc.getId(), newName);
				ct.close();
			} catch (final Exception e) {
				_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
			}
		}

	}

	private void ChangeName(final L1PcInstance pc, final String text) {
		// 改名 By srwh
		final String oldName = pc.getName();
		final String newName = text;
		Connection con = null;
		PreparedStatement pres = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pres = con
					.prepareStatement("UPDATE characters SET char_name=?WHERE char_name=?");
			pres.setString(1, newName);
			pres.setString(2, oldName);
			pres.execute();
		} catch (final SQLException e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(con);
			SQLUtil.close(pres);
		}
	}

	private boolean doesCharNameExist(String name) {
		boolean result = CharObjidTable.get().charObjid(name) != 0 || RobotTable.getInstance().checkName(name);
//		java.sql.Connection con = null;
//		PreparedStatement pstm = null;
//		ResultSet rs = null;
//		try {
//			con = DatabaseFactory.get().getConnection();
//			pstm = con
//					.prepareStatement("SELECT account_name FROM characters WHERE char_name=?");
//			pstm.setString(1, name);
//			rs = pstm.executeQuery();
//			result = rs.next();
//		} catch (final SQLException e) {
//			_log.warning("could not check existing charname:" + e.getMessage());
//		} finally {
//			SQLUtil.close(rs);
//			SQLUtil.close(pstm);
//			SQLUtil.close(con);
//		}
		return result;
	}

	private boolean isAlphaNumeric(final String s) {
		boolean flag = true;
		final char ac[] = s.toCharArray();
		int i = 0;
		do {
			if (i >= ac.length) {
				break;
			}
			if (!Character.isLetterOrDigit(ac[i])) {
				flag = false;
				break;
			}
			i++;
		} while (true);
		return flag;
	}

	private boolean isInvalidName(final String name) {
		int numOfNameBytes = 0;
		final String CLIENT_LANGUAGE_CODE = Config.CLIENT_LANGUAGE_CODE;
		try {
			numOfNameBytes = name.getBytes(CLIENT_LANGUAGE_CODE).length;
		} catch (final UnsupportedEncodingException e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
			return false;
		}
		if (this.isAlphaNumeric(name)
				// 字串位元長度 > 4 時，才允許建立名稱
				&& numOfNameBytes >= 3 && numOfNameBytes <= 12
				&& !BadNamesList.getInstance().isBadName(name)) {
			return false;
		}
		return true;
	}

	private void leaveClan(final L1PcInstance player) {
		final String player_name = player.getName();
		final String clan_name = player.getClanname();
		final int clan_id = player.getClanid();
		if (clan_id == 0) {// クラン未所属
			return;
		}

		final L1Clan clan = WorldClan.get().getClan(clan_name);
		if (clan != null) {
			final String clan_member_name[] = clan.getAllMembers();
			int i;
			if (player.isCrown() && player.getId() == clan.getLeaderId()) { // プリンスまたはプリンセス、かつ、血盟主
				final int castleId = clan.getCastleId();
				final int houseId = clan.getHouseId();
				if (castleId != 0 || houseId != 0) {
					player.sendPackets(new S_ServerMessage(665)); // \f1城やアジトを所有した状態で血盟を解散することはできません。
					return;
				}
				for (final L1War war : WorldWar.get().getWarList()) {
					if (war.checkClanInWar(clan_name)) {
						player.sendPackets(new S_ServerMessage(302)); // \f1解散させることができません。
						return;
					}
				}

				for (i = 0; i < clan_member_name.length; i++) { // クラン員のクラン情報をクリア
					final L1PcInstance online_pc = L1World.getInstance().getPlayer(clan_member_name[i]);
					if (online_pc != null) { // オンライン中のクラン員
						online_pc.setClanid(0);
						online_pc.setClanname("");
						online_pc.setClanRank(0);
						online_pc.setTitle("");
						online_pc.sendPackets(new S_ServerMessage(269,
								player_name, clan_name)); // %1血盟の血盟主%0が血盟を解散させました。
					} else { // オフライン中のクラン員
						try {
							final L1PcInstance offline_pc = CharacterTable.getInstance().restoreCharacter(clan_member_name[i]);
							offline_pc.setClanid(0);
							offline_pc.setClanname("");
							offline_pc.setClanRank(0);
							offline_pc.setTitle("");
							offline_pc.save(); // DBにキャラクター情報を書き込む
						} catch (final Exception e) {
							_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
						}
					}
				}
				// 資料刪除
				ClanEmblemReading.get().deleteIcon(clan_id);
				/*
				 * final String emblem_file = String.valueOf(oldClanId); final
				 * File file = new File("emblem/" + emblem_file); file.delete();
				 */
				ClanReading.get().deleteClan(clan_name);
			} else { // 血盟主以外
				final L1PcInstance clanMember[] = clan.getOnlineClanMember();
				for (i = 0; i < clanMember.length; i++) {
					clanMember[i].sendPackets(new S_ServerMessage(178,
							player_name, clan_name)); // \f1%0が%1血盟を脱退しました。
				}
				if (clan.getWarehouseUsingChar() == player.getId()) { // 自キャラがクラン倉庫使用中

					clan.setWarehouseUsingChar(0); // クラン倉庫のロックを解除
				}
				player.setClanid(0);
				player.setClanname("");
				player.setClanRank(0);
				player.setTitle("");
				clan.delMemberName(player_name);
			}
		} else {
			player.setClanid(0);
			player.setClanname("");
			player.setClanRank(0);
			player.setTitle("");
			player.sendPackets(new S_ServerMessage(178, player_name, clan_name)); // \f1%0が%1血盟を脱退しました。
		}
	}

	/** 移除相關好友清單 */
	private void removeBuddys(L1PcInstance pc) {
		final String pc_name = pc.getName();
		try {
			BuddyTable.getInstance().clearbychangename(pc.getId(), pc_name);// 移除好友清單
			BuddyTable.getInstance().clearbychangename2(pc_name);// 移除好友清單

			for (final L1PcInstance buddys : L1World.getInstance().getAllPlayers()) {
				// BuddyTable.getInstance().removeBuddy(buddys.getId(),
				// pc_name);
				if (pc != buddys) {
					BuddyTable.getInstance().getBuddyTable(buddys.getId())
							.remove(pc_name);
				}
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
	}
}
